"""
Prometheus 监控数据查询客户端模块。
EN: Prometheus monitoring data query client module.

该模块提供了一个 `Prometheus` 类，用于连接 Prometheus 服务并查询资源指标，
包括 Pod 的 CPU、内存、GPU 使用情况以及机器级别的指标。
EN: This module provides a `Prometheus` class for connecting to the Prometheus service and querying resource metrics,
including CPU, memory, and GPU usage for Pods, as well as machine-level metrics.
"""

# 导入 datetime 模块，用于处理日期和时间
# EN: Import the datetime module, used for handling dates and times
import datetime
# 导入 json 模块，用于处理 JSON 数据
# EN: Import the json module, used for handling JSON data
import json

# 导入 pysnooper 模块，用于调试（此处被注释掉，但保留导入）
# EN: Import the pysnooper module, used for debugging (commented out here, but import retained)
import pysnooper
# 导入 requests 模块，用于发送 HTTP 请求
# EN: Import the requests module, used for sending HTTP requests
import requests


class Prometheus:
    """
    Prometheus 客户端，用于查询 Prometheus 监控数据。
    EN: Prometheus client, used for querying Prometheus monitoring data.
    """

    def __init__(self, host: str = ''):
        """
        初始化 Prometheus 客户端。
        EN: Initializes the Prometheus client.

        Args:
            host (str, optional): Prometheus 服务的主机地址。默认为空字符串。
            EN: host (str, optional): The host address of the Prometheus service. Defaults to an empty string.
        """
        # Prometheus 查询范围数据的 API 路径
        # EN: Prometheus API path for querying range data
        #  '/api/v1/query_range'    查看范围数据
        #  '/api/v1/query'    瞬时数据查询
        self.host = host
        # 瞬时数据查询的完整 URL
        # EN: Full URL for instant data queries
        self.query_path = 'http://%s/api/v1/query' % self.host
        # 范围数据查询的完整 URL
        # EN: Full URL for range data queries
        self.query_range_path = 'http://%s/api/v1/query_range' % self.host

        # @pysnooper.snoop()

    def get_resource_metric(self, pod_name: str, namespace: str) -> dict:
        """
        获取指定 Pod 在特定命名空间下的资源使用指标（CPU、内存、GPU）。
        EN: Retrieves resource usage metrics (CPU, memory, GPU) for a specified Pod in a given namespace.

        查询过去一天的数据，步长为 1 分钟。
        EN: Queries data for the past day with a step of 1 minute.

        Args:
            pod_name (str): Pod 的名称，支持模糊匹配。
            EN: pod_name (str): The name of the Pod, supports fuzzy matching.
            namespace (str): Pod 所在的命名空间。
            EN: namespace (str): The namespace where the Pod is located.

        Returns:
            dict: 包含 'cpu' (最大 CPU 使用率), 'memory' (最大内存使用量 GB), 'gpu' (平均 GPU 使用率) 的字典。
            EN: dict: A dictionary containing 'cpu' (max CPU usage), 'memory' (max memory usage in GB), 'gpu' (average GPU usage).
        """
        # 初始化最大 CPU、最大内存和平均 GPU 使用率
        # EN: Initialize max CPU, max memory, and average GPU usage
        max_cpu = 0
        max_mem = 0
        ave_gpu = 0

        # 内存使用量的 Prometheus 查询表达式，获取 Pod 在 30 分钟内的最大内存工作集字节数
        # EN: Prometheus query expression for memory usage, getting the maximum memory working set bytes for the Pod within 30 minutes
        # 这个pod  30分钟内的最大值
        mem_expr = (
            "sum by (pod) (container_memory_working_set_bytes{namespace='%s',"
            " pod=~'%s.*',container!='POD', container!=''})" % (namespace, pod_name)
        )
        # print(mem_expr)
        # 构建内存查询的参数
        # EN: Construct parameters for memory query
        params = {
            'query': mem_expr,
            'start': (
                datetime.datetime.now() - datetime.timedelta(days=1) - datetime.timedelta(hours=8)
            ).strftime('%Y-%m-%dT%H:%M:%S.000Z'),
            'end': datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S.000Z'),
            'step': '1m',  # 运行小于1分钟的，将不会被采集到
            # 'timeout':"30s"
        }
        # 打印查询参数
        # EN: Print query parameters
        print(params)

        try:
            # 发送 HTTP GET 请求查询内存指标
            # EN: Send HTTP GET request to query memory metrics
            res = requests.get(url=self.query_range_path, params=params)
            # 解析 JSON 响应
            # EN: Parse JSON response
            metrics = json.loads(res.content.decode('utf8', 'ignore'))
            # 检查响应状态是否为 'success'
            # EN: Check if the response status is 'success'
            if metrics['status'] == 'success':
                metrics = metrics['data']['result']
                # 如果有返回指标数据
                # EN: If metrics data is returned
                if metrics:
                    metrics = metrics[0]['values']
                    # 遍历指标值，更新最大内存使用量
                    # EN: Iterate through metric values, update maximum memory usage
                    for metric in metrics:
                        if int(metric[1]) > max_mem:
                            max_mem = int(metric[1]) / 1024 / 1024 / 1024  # 转换为 GB

        except Exception as e:
            # 打印异常信息
            # EN: Print exception information
            print(e)

        # CPU 使用率的 Prometheus 查询表达式
        # EN: Prometheus query expression for CPU usage
        cpu_expr = (
            'sum by (pod) (rate(container_cpu_usage_seconds_total'
            "{namespace='%s',pod=~'%s.*',container!='POD'}[1m]))" % (namespace, pod_name)
        )

        # 构建 CPU 查询的参数
        # EN: Construct parameters for CPU query
        params = {
            'query': cpu_expr,
            'start': (
                datetime.datetime.now() - datetime.timedelta(days=1) - datetime.timedelta(hours=8)
            ).strftime('%Y-%m-%dT%H:%M:%S.000Z'),
            'end': datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S.000Z'),
            'step': '1m',  # 运行小于1分钟的，将不会被采集到
            # 'timeout':"30s"
        }
        # 打印查询参数
        # EN: Print query parameters
        print(params)
        try:
            # 发送 HTTP GET 请求查询 CPU 指标
            # EN: Send HTTP GET request to query CPU metrics
            res = requests.get(url=self.query_range_path, params=params)
            # 解析 JSON 响应
            # EN: Parse JSON response
            metrics = json.loads(res.content.decode('utf8', 'ignore'))
            # 检查响应状态是否为 'success'
            # EN: Check if the response status is 'success'
            if metrics['status'] == 'success':
                metrics = metrics['data']['result']
                # 如果有返回指标数据
                # EN: If metrics data is returned
                if metrics:
                    metrics = metrics[0]['values']
                    # 遍历指标值，更新最大 CPU 使用率
                    # EN: Iterate through metric values, update maximum CPU usage
                    for metric in metrics:
                        if float(metric[1]) > max_cpu:
                            max_cpu = float(metric[1])
        except Exception as e:
            # 打印异常信息
            # EN: Print exception information
            print(e)

        # GPU 使用率的 Prometheus 查询表达式
        # EN: Prometheus query expression for GPU usage
        gpu_expr = (
            'avg by (exported_pod)'
            " (DCGM_FI_DEV_GPU_UTIL{exported_namespace='%s',exported_pod=~'%s.*'})"
            % (namespace, pod_name)
        )

        # 构建 GPU 查询的参数
        # EN: Construct parameters for GPU query
        params = {
            'query': gpu_expr,
            'start': (
                datetime.datetime.now() - datetime.timedelta(days=1) - datetime.timedelta(hours=8)
            ).strftime('%Y-%m-%dT%H:%M:%S.000Z'),
            'end': datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S.000Z'),
            'step': '1m',  # 运行小于1分钟的，将不会被采集到
            # 'timeout':"30s"
        }
        # 打印查询参数
        # EN: Print query parameters
        print(params)
        try:
            # 发送 HTTP GET 请求查询 GPU 指标
            # EN: Send HTTP GET request to query GPU metrics
            res = requests.get(url=self.query_range_path, params=params)
            # 解析 JSON 响应
            # EN: Parse JSON response
            metrics = json.loads(res.content.decode('utf8', 'ignore'))
            # 检查响应状态是否为 'success'
            # EN: Check if the response status is 'success'
            if metrics['status'] == 'success':
                metrics = metrics['data']['result']
                # 如果有返回指标数据
                # EN: If metrics data is returned
                if metrics:
                    metrics = metrics[0]['values']
                    # 提取所有 GPU 使用率并计算平均值
                    # EN: Extract all GPU usage rates and calculate the average
                    all_util = [float(metric[1]) for metric in metrics]
                    ave_gpu = sum(all_util) / len(all_util)
        except Exception as e:
            # 打印异常信息
            # EN: Print exception information
            print(e)

        # 返回整理后的资源指标
        # EN: Return the organized resource metrics
        return {'cpu': round(max_cpu, 2), 'memory': round(max_mem, 2), 'gpu': round(ave_gpu, 2)}

    @pysnooper.snoop()
    def get_machine_metric(self) -> dict:
        """
        获取机器级别的监控指标，例如 Pod 数量。
        EN: Retrieves machine-level monitoring metrics, such as the number of Pods.

        Returns:
            dict: 包含机器指标的字典，例如 'pod_num' (每个节点的 Pod 数量)。
            EN: dict: A dictionary containing machine metrics, e.g., 'pod_num' (number of Pods per node).
        """
        # 定义需要查询的机器指标及其 Prometheus 表达式
        # EN: Define machine metrics to query and their Prometheus expressions
        # 这个pod  30分钟内的最大值
        metrics = {'pod_num': 'sum(kubelet_running_pod_count)by (node)', 'request_mem': ''}
        # 初始化返回结果字典
        # EN: Initialize the dictionary for return results
        back = {}
        # 遍历所有需要查询的指标
        # EN: Iterate through all metrics to be queried
        for metric_name in metrics:
            # print(mem_expr)
            # 构建查询参数
            # EN: Construct query parameters
            params = {'query': metrics[metric_name], 'timeout': '30s'}
            # 打印查询参数
            # EN: Print query parameters
            print(params)
            # 为当前指标名初始化结果字典
            # EN: Initialize result dictionary for the current metric name
            back[metric_name] = {}

            try:
                # 发送 HTTP GET 请求查询指标
                # EN: Send HTTP GET request to query metrics
                res = requests.get(url=self.query_path, params=params)
                # 解析 JSON 响应
                # EN: Parse JSON response
                metrics = json.loads(res.content.decode('utf8', 'ignore'))
                # 检查响应状态是否为 'success'
                # EN: Check if the response status is 'success'
                if metrics['status'] == 'success':
                    metrics = metrics['data']['result']
                    # 如果有返回指标数据
                    # EN: If metrics data is returned
                    if metrics:
                        # 遍历指标结果
                        # EN: Iterate through metric results
                        for metric in metrics:
                            # 获取节点名称
                            # EN: Get node name
                            node = metric['metric']['node']
                            # 如果节点名称包含冒号，则截取冒号之前的部分
                            # EN: If the node name contains a colon, truncate to the part before the colon
                            if ':' in node:
                                node = node[: node.index(':')]
                            # 获取指标值
                            # EN: Get metric value
                            value = metric['value'][1]
                            # 将指标值存储到结果字典中
                            # EN: Store the metric value in the result dictionary
                            back[metric_name][node] = int(value)

            except Exception as e:
                # 打印异常信息
                # EN: Print exception information
                print(e)

        # 返回机器指标数据
        # EN: Return machine metrics data
        return back


# 以下是被注释掉的示例代码，目前未使用。
# EN: The following is commented-out example code, currently not in use.
# if __name__ == "__main__":
#     prometheus = Prometheus('10.101.142.128:8081')
#     prometheus.get_machine_metric()
